// 参考： https://threejsfundamentals.org/threejs/lessons/threejs-post-processing.html
import { 
  PerspectiveCamera,
  Scene, 
  WebGLRenderer,
  Vector3,
  Color,
  HemisphereLight,
  DirectionalLight,
  Mesh,
  BoxBufferGeometry,
  ShadowMaterial,
  MeshLambertMaterial,
  InstancedMesh,
  Matrix4,
  IcosahedronBufferGeometry,
} from "three";
// 调用
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GUI } from "dat.gui";
import { AmmoPhysics } from 'three/examples/jsm/physics/AmmoPhysics';
import Stats from 'three/examples/jsm/libs/stats.module';

const scene = new Scene();
scene.background = new Color(0x666666);

const camera = setCamera();
const renderer = setRenderer();
const trackballControls = new OrbitControls(camera, renderer.domElement);
let boxes: InstancedMesh, spheres: InstancedMesh, physics: AmmoPhysics, position: Vector3 

let js = document.createElement('script');
js.src = '/ammo/ammo.wasm.js';
js.onload = async function() {
  console.log('down');

  // @ts-ignore
  physics = await AmmoPhysics();
  position = new Vector3();

  const hemiLight = new HemisphereLight();
  hemiLight.intensity = 0.35;
  scene.add(hemiLight);

  const dirLight = new DirectionalLight();
  dirLight.position.set(5, 5, 5);
  dirLight.castShadow = true;
  dirLight.shadow.camera.zoom = 2;
  scene.add(dirLight);

  const floor = new Mesh(
    new BoxBufferGeometry(10, 5, 10),
    new ShadowMaterial({ color: 0x111111  })
  );
  floor.position.y = -2.5;
  floor.receiveShadow = true;
  scene.add(floor);
  (<any>physics).addMesh(floor);

  const material = new MeshLambertMaterial();
  const matrix = new Matrix4();
  const color = new Color();

  const geometryBox = new  BoxBufferGeometry(0.1, 0.1, 0.1);
  boxes = new InstancedMesh(geometryBox, material, 100);
  boxes.castShadow = true;
  boxes.receiveShadow = true;
  scene.add(boxes);

  for (let i = 0; i < boxes.count; i++) {
    matrix.setPosition(Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5);
    boxes.setMatrixAt(i, matrix);
    boxes.setColorAt(i, color.setHex(0xffffff * Math.random()))
  }

  physics.addMesh(boxes, 1);

  const geometrySphere = new IcosahedronBufferGeometry(0.075, 3);
  spheres = new InstancedMesh(geometrySphere, material, 100);
  spheres.castShadow = true;
  spheres.receiveShadow = true;
  scene.add(spheres);

  for (let i = 0; i < spheres.count; i++) {
    matrix.setPosition(Math.random() - 0.5, Math.random() * 2, Math.random() - 0.5);
    spheres.setMatrixAt(i, matrix);
    spheres.setColorAt(i, color.setHex(0xffffff * Math.random()));
  }
  physics.addMesh(spheres, 1);

  render();
}
document.body.appendChild(js);

// @ts-ignore
const stats = new Stats();
document.body.appendChild(stats.dom)

function render() {
  stats.update();
  trackballControls.update();

  let index = Math.floor(Math.random() * boxes.count);

  position.set(0, Math.random() +1, 0);
  physics.setMeshPosition(boxes, position, index);

  index = Math.floor(Math.random() * spheres.count);

  position.set(0, Math.random() +1, 0);
  physics.setMeshPosition(spheres, position, index);


  requestAnimationFrame(render);
  renderer.render(scene, camera);
}

function setRenderer() {
  const renderer = new WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 支持阴影生成 
  renderer.shadowMap.enabled = true;
  document.body.appendChild(renderer.domElement);

  return renderer
}

function setCamera(): PerspectiveCamera {
  let camera = new PerspectiveCamera(50, window.innerWidth/window.innerHeight, 0.1, 100);
  camera.position.set(-1, 1.5, 2);
  camera.lookAt(0, 0.5, 0);

  return camera;
}
